package ru.niir.goodfil.ui.quick;

import org.apache.commons.lang.StringUtils;
import ru.niir.goodfil.audit.domain.OrderItemUIEvent;
import ru.niir.goodfil.audit.domain.enums.OrderItemUIEventType;
import ru.niir.goodfil.db.*;
import ru.niir.goodfil.ui.BlockExchangeBean;
import ru.niir.goodfil.ui.PageBean;
import ru.niir.goodfil.ui.SecurityBean;
import ru.niir.goodfil.ui.tasks.CountDownTask;
import ru.niir.goodfil.ui.utils.FacesUtils;
import ru.niir.goodfil.utils.PriceInfo;
import ru.niir.goodfil.utils.filters.GoodsFilter;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import static ru.niir.goodfil.utils.Utils._assert;

public class QuickOrderBean extends PageBean {
    private final List<Good> goods = new ArrayList<Good>();

    private int index = -1;

    private String goodCode;

    private String selectTheGoodCode;

    private String lastError;

    private QuickOrderGood current;

    private void setSelected(int index) {
        for (Good good : goods) {
            good.setSelected(goods.indexOf(good) == index);
        }
    }

    public void up() {
        if (goods.size() > 0) {
            if (index == -1) {
                index = goods.size() - 1;
            } else if (index > 0) index--;
        } else {
            index = -1;
        }

        setSelected(index);
    }

    public void down() {
        if (goods.size() > 0) {
            if (index == -1) {
                index = 0;
            } else if (index < goods.size() - 1) {
                index++;
            } else {
                index = goods.size() - 1;
            }
        } else {
            index = -1;
        }

        setSelected(index);
    }

    public void clear() {
        goods.clear();
        index = -1;
    }

    public void updateGoodsList() {
        goods.clear();
        if (!StringUtils.isBlank(goodCode)){
            GoodsFilter goodsFilter=GoodsFilter.byCodeWithoutSpaces(goodCode.replaceAll(" ", ""));
            goods.addAll(gf().getGoods(0, 10, goodsFilter));
        }
        if (goods.size() == 1) index = 0;
        setSelected(index);
    }

    public void selectGood() {
        setLastError(null);

        current = null;
        if (index >= 0 && index < goods.size()) {
           // loadGoodInfo(goods.get(index));
            loadGoodInfo(gf().getGoodByCode(goods.get(index).getCode()));
        }
    }

    public void selectTheGood() {
        setLastError(null);
        current = null;
        loadGoodInfo(gf().getGoodByCode(selectTheGoodCode));
    }

    private void loadGoodInfo(Good currentGood) {
        if (currentGood == null) return;

        current = new QuickOrderGood();
        current.setGoodCode(currentGood.getCode());
        current.setGoodName(currentGood.getName());
        current.setCount("");
        current.setFree(String.valueOf(currentGood.getCount() - currentGood.getReservedCount()));

        PriceInfo priceInfo = gf().getPrice2(currentGood, getSessionBean().getOrder().getClient());

        current.setFirstprice(String.valueOf(priceInfo.getPrice()));
        current.setPrice(String.valueOf(priceInfo.getPrice()));
        current.setPackageCount(currentGood.getPackageCount());
    }


    public QuickOrderGood getCurrent() {
        return current;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public String getGoodCode() {
        return goodCode;
    }

    public void setGoodCode(String goodCode) {
        this.goodCode = goodCode;
    }

    public String getLastError() {
        return lastError;
    }

    public void setLastError(String lastError) {
        this.lastError = lastError;
    }

    public List<Good> getGoods() {
        return goods;
    }

    public String getSelectTheGoodCode() {
        return selectTheGoodCode;
    }

    public void setSelectTheGoodCode(String selectTheGoodCode) {
        this.selectTheGoodCode = selectTheGoodCode;
    }

    public void addGood() {
        lastError = null;

        //  Проверяем что данный заказ вообще можно изменять
        if(!gf().getIsReservedOn()){
            if (!getSessionBean().getOrder().getOrderStateIsBeforeSaved()) {
                lastError = "Данный заказ не подлежит изменению";
                return;
            }
        }
        else {
            if (!getSessionBean().getOrder().getOrderIsEditableWithReserves()) {
                lastError = "Данный заказ не подлежит изменению";
                return;
            }
        }

        float firstPrice = 0;
        String goodCode = current.getGoodCode();
        try {
            firstPrice = Float.parseFloat(current.getFirstprice());
        } catch (NumberFormatException nfe) {
            lastError = "Начальная цена задана неверно";
            return;
        }

        int goodCount = 0;
        float price = 0;

        try {
            goodCount = Integer.parseInt(current.getCount());
        } catch (NumberFormatException nfe) {
            lastError = "Количество товара задано неверно";
            return;
        }

        try {
            price = Float.parseFloat(current.getPrice());
        } catch (NumberFormatException nfe) {
            lastError = "Цена товара задана неверно";
            return;
        }

        //  Проверяем, что количество товара положительно
        if (goodCount <= 0) {
            lastError = "Количество товара должно быть положительным числом";
            return;
        }

        //  Проверяем, что цена товара положительна
        if (price <= 0) {
            lastError = "Цена товара должна быть положительным числом";
            return;
        }

        //  Проверяем, что новая цена не меньше старой
        if (price < firstPrice) {
            lastError = "Цена не должна быть ниже цены из прайса";
            return;
        }

        Good good = gf().getGoodByCode(goodCode);

        try {
            //  Проверяем введенное количество товара
            int realGoodCount = good.getCount() - good.getReservedCount();
            if (realGoodCount < goodCount) {   //  Товара не хватает на складе
                lastError = "Товара на складе не хватает";
                return;
            }

            if (good.getC1CodeIsMissing()) {   //  Нет кода соответствие с 1С
                lastError = "У товара нет кода соответствия с 1С";
                return;
            }

            //  Получаем элементы заказа
            List<OrderItem> orderItems = getSessionBean().getOrderItems();

            //  Проводим склейку
            for (OrderItem orderItem : orderItems) {
                if (orderItem.getGoodId() == good.getId()) {
                    //  Предотвращение повторной выборки товара
                    if (good.getCount() < (orderItem.getCount() + goodCount)) {
                        lastError = "Недостаточно товара";
                        return;
                    }

                    //  Склеиваем
                    orderItem.setCount(orderItem.getCount() + goodCount);
                    getSessionBean().setOrderItems(orderItems);
                    // Если включены резервы в ИС и статус не предварительно сохранен,
                    // то обновляем количество зарезервированно товара
                    boolean isReservedOn = gf().getIsReservedOn();
                    boolean orderStateIsNotPreSaved = !gf().getOrderById(getSessionBean().getSelectedOrderId()).getOrderStateIsPreSaved();
                    if(isReservedOn && orderStateIsNotPreSaved){
                        good.setReservedCount(good.getReservedCount() + goodCount);
                        gf().updateGood(good);
                        // обновляем список товаров, для того, чтобы отобразилось реальное количество
                        updateGoodsList();
                    }
                    return;
                }
            }

            //  Добавляем в заказ новую позицию
            PriceInfo pi = gf().getPrice2(good.getId(),
                    good.getBrandId(),
                    getSessionBean().getSelectedClientId(),
                    getSessionBean().getSelectedClientGroupId2(good.getBrandId()));
            OrderItem orderItem = new OrderItem();

            orderItem.setGoodId(good.getId());
            orderItem.setOrderId(getSessionBean().getSelectedOrderId());
            orderItem.setCount(goodCount);
            orderItem.setStartPrice(pi.getPrice());
            orderItem.setPersonalPrice(pi.isPersonalPrice());

            if (pi.getPrice() != price) {
                orderItem.setManualPrice(price);
            }


            orderItems.add(orderItem);
            orderItem.setGood(good);
            getSessionBean().setOrderItems(orderItems);
            if(gf().getIsReservedOn() && !gf().getOrderById(getSessionBean().getSelectedOrderId()).getOrderStateIsPreSaved()){
                good.setReservedCount(good.getReservedCount() + goodCount);
                gf().updateGood(good);
                // обновляем список товаров, для того, чтобы отобразилось реальное количество
                updateGoodsList();
            }
            lastError = null;
//          Order order = gf().getOrderById(getSessionBean().getSelectedOrderId());
//          getAuditService().logOrderItemUIEvent(prepareOrderItemUIEvent(OrderItemUIEventType.ADDED, order, orderItem));
        } catch (Exception e) {
            e.printStackTrace();
            lastError = "Ошибка при добавлении позиции в заказ";
        }
    }

    private OrderItemUIEvent prepareOrderItemUIEvent(OrderItemUIEventType type, Order order, OrderItem orderItem) {
        OrderItemUIEvent event = new OrderItemUIEvent();

        event.setIp(getAuditHelper().getIp());
        event.setLogin(getAuditHelper().getLogin());
        event.setType(type);

        event.setOrderId(String.valueOf(order.getId()));
        event.setC1Num(order.getC1Num());

        Client client = order.getClient();
        if (client == null) client = gf().getClientById(order.getClientId());
        event.setClientId(String.valueOf(client.getId()));
        event.setClientName(client.getCompanyName());

        User manager = order.getManager();
        if (manager == null) manager = gf().getUserById(order.getManagerId());
        event.setManagerId(String.valueOf(manager.getId()));
        event.setManagerName(manager.getFio());

        event.setCreationDate(order.getCreationDateAsString());
        event.setDeliveryDate(order.getDeliveryDateAsString());
        event.setOrderSum(String.valueOf(order.getSum()));

        Good good = orderItem.getGood();
        if (good == null) good = gf().getGoodById(orderItem.getGoodId());

        event.setGoodId(String.valueOf(good.getId()));
        event.setGoodCode(good.getCode());

        event.setCount(String.valueOf(orderItem.getCount()));
        event.setPrice(String.valueOf(orderItem.getItemPrice()));

        return event;
    }

    public static class QuickOrderGood implements Serializable {
        private String goodCode;

        private String goodName;

        private String free;

        private String count;

        private String firstprice;

        private String price;
        
        private String packageCount;

        public String getGoodCode() {
            return goodCode;
        }

        public void setGoodCode(String goodCode) {
            this.goodCode = goodCode;
        }

        public String getGoodName() {
            return goodName;
        }

        public void setGoodName(String goodName) {
            this.goodName = goodName;
        }

        public String getFree() {
            return free;
        }

        public void setFree(String free) {
            this.free = free;
        }

        public String getCount() {
            return count;
        }

        public void setCount(String count) {
            this.count = count;
        }

        public String getFirstprice() {
            return firstprice;
        }

        public void setFirstprice(String firstprice) {
            this.firstprice = firstprice;
        }

        public String getPrice() {
            return price;
        }

        public void setPrice(String price) {
            this.price = price;
        }

        public String getPackageCount() {
            return packageCount;
        }

        public void setPackageCount(String packageCount) {
            this.packageCount = packageCount;
        }
    }

    public String getManagerForBlock() {
        long managerId=CountDownTask.getManagerIdBloked();
        String result = "";
        if (managerId == -1) {
            result = "всех";
            return result;
        }
        for (User manager : gf().getManagers()) {
            _assert(manager != null);
            if (manager == null) continue;
            if (manager.getId() == managerId) {
                result = "всех, кроме ".concat(manager.getFio());
                break;
            }
        }
        return result;
    }

    public boolean isPrivelegeUser() {
        SecurityBean securityBean = (SecurityBean) FacesUtils.getManagedBean("SecurityBean");
        BlockExchangeBean blockExchangeBean = (BlockExchangeBean) FacesUtils.getManagedBean("BlockExchangeBean");
        if (isBlock()) {
            if ((securityBean.getCurrentUser().getId() == CountDownTask.getManagerIdBloked())) {
                return true;
            }
        }
        return false;
    }

   public boolean isBlock(){
        if (CountDownTask.getTimerValue() > 0) {
            return true;
        } else {
            return false;
        }
    }
}
